package thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: wx
 * Date: 2023-12-07
 * Time: 13:56
 */
public class ThreadDemo14 {


    private static long result = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            long tmp = 0;
            for (long i = 0; i < 50_0000_0000L ; i++) {
                tmp += i;
            }
            result += tmp;
        });
        Thread t2 = new Thread(() -> {
            long tmp = 0;
            for (long i = 0; i < 50_0000_0000L ; i++) {
                tmp += i;
            }
            result += tmp;

            /*try {
                t1.join();
                //如果把 join 加到末尾,t1 和 t2 并发执行,没啥区别
                //如果把 join 加到开头,这个时候,就是先执行t1, t2先阻塞,等到 t 执行完毕,t2继续执行,又成了串行执行.
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }*/
        });

        //这个写法下,创建两线程,并发执行,主线程等待两线程结束;
        t1.start();
        t2.start();
        long beg = System.currentTimeMillis();
        //多线程是能够有效的提高程序的运行效率的
        t1.join();
        t2.join();
        long end = System.currentTimeMillis();

        //这个写法就是启动第一个线程结束,等待第一个线程结束,在启动第二个线程,本质上也是穿行执行
        /*
        t1.start();
        long beg = System.currentTimeMillis();
        //多线程是能够有效的提高程序的运行效率的
        t1.join();
        t2.start();
        t2.join();
        long end = System.currentTimeMillis();*/

        //主线程用过 join 等待,这两线程结束
        //t 和 t2 都执行结束之后,此时主线程才能继续向下执行
        // 才能打印结果和计算时间.

        System.out.println("result =" + result);
        System.out.println("time = " + (beg - end) + "ms");

        /*start() 的使命,就是为了立即在内核中创建出一个新的线程
        新的线程和之前的线程,是并发执行的关系
        串行就是单个执行,
        并发执行指多个线程同时/一起执行
        串行化,这些事务一个接一个串行执行*/

        /*
        join() 有三个版本:
        1)死等: (不见不散) 不科学的, 因为程序中死等,会导致程序卡住,
                                 无法继续后续的逻辑,是非常严重的bug;
        2)带有超时时间的join,join有一个时间上限,
                          到了超时时间,就不去等待了,该继续做什么就继续做什么;
        3)可以设置到纳秒级别

        也可以给一种指令结束等待 interrupt就是一种方法;
        在计算机中,但凡涉及到等待的操作,一般不建议使用"死等"的策略
         */
    }

    public static void main4(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (long i = 0; i < 50_0000_0000L ; i++) {
                result += i;
            }
        });
        Thread t2 = new Thread(() -> {
            for (long i = 0; i < 50_0000_0000L ; i++) {
                result += i;
            }
        });
        t1.start();
        t2.start();
        long beg = System.currentTimeMillis();
                                                   //多线程是能够有效的提高程序的运行效率的
        t1.join();
        t2.join();
        long end = System.currentTimeMillis();

        System.out.println("result =" + result);
        System.out.println("time = " + (beg - end) + "ms");

    }

    public static void main3(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (long i = 0; i < 100_0000_0000L ; i++) {
                result += i;
            }
        });
        t.start();
        long beg = System.currentTimeMillis();

        t.join();
        long end = System.currentTimeMillis();

        System.out.println("result =" + result);
        System.out.println("time = " + (beg - end) + "ms");
    }
    //t线程吧计算的结果放到result中.
    private static int result1 = 0;
    public static void main2(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i <1000 ; i++) {
                result1 += i;
            }
        });
        t.start();

        //Thread.sleep(1000);
        //由于执行时间无法确定,所以得使用 join

        t.join();
        // 使用 join,就会严格按照 t 线程执行结束来作为等待的条件.
        // 什么时候 t 线程运行结束(执行完毕),什么时候,join就结束等待
        // t 线程 运行 1ms,join就等待 1ms;
        // join可以确保得到的结果一定是靠谱的结果.


        System.out.println("result =" + result1);
    }
    public static void main1(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i <1000 ; i++) {
                result += i;
            }
        });
        t.start();
        //不知道 t 线程要执行多久
        Thread.sleep(1000);

        // 如果直接打印 result,此时得到的结果是不确定的
        // 这是由于线程之间的执行顺序不确定,主线程打印 result 可能是还没有开始计算的初始值 0
        // 也可能是计算过程中的中间结果,也可能是 t 线程计算完成之后的最终结果.
        System.out.println("result =" + result);

        //获取线程引用
        Thread.currentThread();//获取当前线程的 引用 (Thread引用)

    }
}
